/* #    FileName   : decode_adaption.c
    #    Created    : 2023年06月20日 星期二 20时40分14秒
	解析扩展字段的逻辑，其中buf是从ts的第五个字节开始，因为前四个字节是ts的头，其中要注意adaption_field_control字段，他表面后面是否有扩展字段
 *****************************/
struct mts_adaptation_field {
    // --> fixed: 8bit
    uint32_t adaptation_field_length : 8;
    // --> unfixed: adaptation_field_length
    uint32_t discontinuity_indicator : 1;
    uint32_t random_access_indicator : 1;
    uint32_t elementary_stream_priority_indicator : 1;
    uint32_t PCR_flag : 1;
    uint32_t OPCR_flag : 1;
    uint32_t splicing_point_flag : 1;
    uint32_t transport_private_data_flag : 1;
    uint32_t adaptation_field_extension_flag : 1;
    uint64_t program_clock_reference_base : 33;  // if (PCR_flag==1)
    uint32_t program_clock_reference_extension : 9;
    uint64_t original_program_clock_reference_base : 33;  // if (OPCR_flag==1)
    uint32_t original_program_clock_reference_extension : 9;
    uint32_t splice_countdown : 8;                   // if (splicing_point_flag==1)
    uint32_t transport_private_data_length : 8;      // if (transport_private_data_flag==1)
    int8_t transport_private_data[64];               // 自规约不超过64字节
    uint32_t adaptation_field_extension_length : 8;  // if (adaptation_field_extension_flag==1)
    uint32_t ltw_flag : 1;
    uint32_t piecewise_rate_flag : 1;
    uint32_t seamless_splice_flag : 1;
    uint32_t ltw_valid_flag : 1;  // if (ltw_flag==1)
    uint32_t ltw_offset : 15;
    uint32_t piecewise_rate : 22;  // if (piecewise_rate_flag==1)
    uint32_t splice_type : 4;      // if (seamless_splice_flag==1)
    int64_t DTS_next_AU : 36;
};

static inline uint32_t mts_dec_adaptation_filed(const uint8_t* data,  // 于adaptation_field起始
                                                size_t bytes,         // 剥离packet_header后的长度
                                                struct mts_adaptation_field* adp) {
    if (bytes > MTS_PACKET_SIZE)
        return -1;
    if (adp == nullptr)
        return -1;
    uint32_t i = 0, j = 0;
    /**
     * Adaptation Field Control
     * ISO_IEC_13818 Table 2-6
     */
    adp->adaptation_field_length = data[i++];  // 8b
    // field
    if (adp->adaptation_field_length > 0) {
        adp->discontinuity_indicator = (data[i] >> 7) & 0x01;               // 1b
        adp->random_access_indicator = (data[i] >> 6) & 0x01;               // 1b
        adp->elementary_stream_priority_indicator = (data[i] >> 5) & 0x01;  // 1b
        adp->PCR_flag = (data[i] >> 4) & 0x01;                              // 1b
        adp->OPCR_flag = (data[i] >> 3) & 0x01;                             // 1b
        adp->splicing_point_flag = (data[i] >> 2) & 0x01;                   // 1b
        adp->transport_private_data_flag = (data[i] >> 1) & 0x01;           // 1b
        adp->adaptation_field_extension_flag = (data[i] >> 0) & 0x01;       // 1b
        i++;
        // PCR
        if (adp->PCR_flag) {
            adp->program_clock_reference_base =
                ((uint64_t)data[i] << 25) | ((uint64_t)data[i + 1] << 17) | ((uint64_t)data[i + 2] << 9) |
                ((uint64_t)data[i + 3] << 1) | ((data[i + 4] >> 7) & 0x01);  // 33b
            // --> reserved: 6b
            adp->program_clock_reference_extension = ((data[i + 4] & 0x01) << 8) | data[i + 5];  // 9b
            i += 6;
        }
        // OPCR
        if (adp->OPCR_flag) {
            adp->original_program_clock_reference_base =
                (((uint64_t)data[i]) << 25) | ((uint64_t)data[i + 1] << 17) | ((uint64_t)data[i + 2] << 9) |
                ((uint64_t)data[i + 3] << 1) | ((data[i + 4] >> 7) & 0x01);  // 33b
            // --> reserved: 6b
            adp->original_program_clock_reference_extension = ((data[i + 4] & 0x01) << 1) | data[i + 5];  // 9b
            i += 6;
        }
        if (adp->splicing_point_flag) {
            adp->splice_countdown = data[i++];  // 8b
        }
        if (adp->transport_private_data_flag) {
            adp->transport_private_data_length = data[i++];  // 8b
            if (adp->transport_private_data_length > 0) {
                memcpy(&adp->transport_private_data, &data[i], adp->transport_private_data_length);
                i += adp->transport_private_data_length;
            }
        } else {
            adp->transport_private_data_length = 0;
        }
        if (adp->adaptation_field_extension_flag) {
            uint8_t reserved;
            adp->adaptation_field_extension_length = data[i++];  // 8b
            adp->ltw_flag = (data[i] >> 7) & 0x01;               // 1b
            adp->piecewise_rate_flag = (data[i] >> 6) & 0x01;    // 1b
            adp->seamless_splice_flag = (data[i] >> 5) & 0x01;   // 1b
            reserved = data[i] & 0x1F;                           // 5b
            i++;
            if (adp->ltw_flag) {
                adp->ltw_valid_flag = (data[i] >> 7) & 0x01;              // 1b
                adp->ltw_offset = ((data[i] & 0x7F) << 8) | data[i + 1];  // 15b
                i += 2;
            }
            if (adp->piecewise_rate_flag) {
                // --> reserved: 2b
                adp->piecewise_rate = ((data[i] & 0x3F) << 16) | (data[i + 1] << 8) | data[i + 2];  // 22b
                i += 3;
            }
            if (adp->seamless_splice_flag) {
                adp->splice_type = (data[i] >> 4) & 0x0F;  // 4b
                adp->DTS_next_AU = (((data[i] >> 1) & 0x07) << 30) | (data[i + 1] << 22) |
                                   (((data[i + 2] >> 1) & 0x7F) << 15) | (data[i + 3] << 7) |
                                   ((data[i + 4] >> 1) & 0x7F);  // 36b
                i += 5;
            }
            // reserved byte
        }
        // stuffing byte
    }
    return 0;
}
